--
--    Health Organizer (http://sourceforge.net/projects/hor/,
--                      http://hor.sourceforge.net/)
--    Copyright (C) 2015-2024  Andrea Urbani ( matfanjol@users.sf.net )
--
--    This program is free software: you can redistribute it and/or modify
--    it under the terms of the GNU General Public License as published by
--    the Free Software Foundation, either version 3 of the License, or
--    (at your option) any later version.
--
--    This program is distributed in the hope that it will be useful,
--    but WITHOUT ANY WARRANTY; without even the implied warranty of
--    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--    GNU General Public License for more details.
--
--    You should have received a copy of the GNU General Public License
--    along with this program.  If not, see <http://www.gnu.org/licenses/>.
--
SET statement_timeout = 0;
SET lock_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SET check_function_bodies = false;
SET client_min_messages = warning;
alter table "tDocumentsFiles" add column "File_oid" oid;
create index "tmpDocFiles" on "tDocumentsFiles"("File_oid");
-- HOR_LONG_OPERATION_START
create or replace function "fixdata" ()
returns boolean
as $$
BEGIN
  declare
  fDoc "tDocumentsFiles"."ID_Document"%TYPE;
  fFil "tDocumentsFiles"."ID_File"%TYPE;
  curFiles cursor for select "ID_Document","ID_File" from "tDocumentsFiles" where "File_oid" is null for update;
  fCount integer;
  fErrors boolean;
  begin
  fCount := 4;
  loop
    fErrors := false;
    open curFiles;
    loop
      fetch curFiles into fDoc, fFil;
      exit when (fDoc is null);
      -- I create the large object from the content
      begin
      update "tDocumentsFiles"
      set "File_oid"=(select lo_from_bytea(0,(select "Content" from "tDocumentsFiles" where "ID_Document"=fDoc and "ID_File"=fFil)))
      where "ID_Document"=fDoc and "ID_File"=fFil;
      exception
        when others then
          -- There could be errors reading the "Content" field
          -- I ignore them, because I will try till a maximum of 4 times
          fErrors := true;
          if ( fCount = 1 ) then
            raise exception 'Not able to convert the content of the files into OID. Try again or try to restart the Postgresql. (Current record: document % file %)',
              fDoc, fFil;
          end if;
      end;
    End loop;
    close curFiles;
    exit when not fErrors;
    fCount := fCount - 1;
    if ( fCount <= 0 ) then
      raise exception 'Not able to convert the content of the files into OID. Try again or try to restart the Postgresql.';
    end if;
  end loop;
	return true;
  End;
END
$$
LANGUAGE plpgsql;
select "fixdata"();
-- HOR_LONG_OPERATION_END
drop function "fixdata"();
drop index "tmpDocFiles";
alter table "tDocumentsFiles" drop column "Content";
alter  TABLE public."tPersons"
  drop constraint "fk_tPersons_tCountriesCitiesAddresses";
alter  TABLE public."tPersons"
 add CONSTRAINT "fk_tPersons_tCountriesCitiesAddresses" FOREIGN KEY ("ID_Country", "ID_City", "ID_Address", "ID_SubGroup1", "ID_SubGroup3", "ID_SubGroup2")
        REFERENCES public."tCountriesCitiesAddresses" ("ID_Country", "ID_City", "ID_Address", "ID_SubGroup1", "ID_SubGroup3", "ID_SubGroup2") MATCH SIMPLE
        ON UPDATE CASCADE
        ON DELETE SET NULL;
alter TABLE public."tPersons"
  drop constraint "fk_tPersons_tCountriesCities_Birth";
alter  TABLE public."tPersons"
 add CONSTRAINT "fk_tPersons_tCountriesCities_Birth" FOREIGN KEY ("ID_Country", "ID_City", "ID_SubGroup1", "ID_SubGroup3", "ID_SubGroup2")
        REFERENCES public."tCountriesCities" ("ID_Country", "ID_City", "ID_SubGroup1", "ID_SubGroup3", "ID_SubGroup2") MATCH SIMPLE
        ON UPDATE CASCADE
        ON DELETE SET NULL;
alter  TABLE public."tPersons"
  add "ID_Father" integer;
alter  TABLE public."tPersons"
  add "ID_Mother" integer;
alter  TABLE public."tPersons"
  add constraint "fk_tPersons_tPersons_Father"
    foreign key ("ID_Father")
      references "tPersons" ("ID")
        ON UPDATE CASCADE
        ON DELETE RESTRICT;
alter  TABLE public."tPersons"
  add constraint "fk_tPersons_tPersons_Mother"
    foreign key ("ID_Mother")
      references "tPersons" ("ID")
        ON UPDATE CASCADE
        ON DELETE RESTRICT;
create TABLE public."tPersonsGroups" (
"ID" serial not null,
"ID_Person" integer not null,
"Name" character varying(35),
constraint "pk_tPersonsGroups" primary key ("ID"),
constraint "udx_tPersonsGroups_PersonName" unique ("ID_Person","Name"),
constraint "fk_tPersonsGroups_tPersons" foreign key ("ID_Person") references "tPersons"("ID") on update cascade on delete cascade
);
create TABLE public."tPersonsGroupsPersons" (
"ID_PersonGroup" integer not null,
"ID_Person" integer not null,
constraint "pk_tPersonsGroupsPersons" primary key ("ID_PersonGroup","ID_Person"),
constraint "fk_tPersonsGroupsPersons_tPersonsGroups" foreign key ("ID_PersonGroup") references "tPersonsGroups"("ID") on update cascade on delete cascade,
constraint "fk_tPersonsGroupsPersons_tPersons" foreign key ("ID_Person") references "tPersons"("ID") on update cascade on delete cascade
);
CREATE TABLE public."tPlaces"
(
    "ID" serial not null,
    "Name" character varying(70) NOT NULL,
    "Note" text,
    "ID_Country" integer,
    "ID_SubGroup1" integer,
    "ID_SubGroup2" integer,
    "ID_SubGroup3" integer,
    "ID_City" integer,
    "ID_Address" integer,
    "Number" character varying(45),
    "Expired" boolean NOT NULL DEFAULT false,
  constraint "pk_tPlaces" primary key ("ID"),
    constraint "udx_tPlaces" unique ("Name"),
    CONSTRAINT "fk_tPlaces_tCountriesCitiesAddresses" FOREIGN KEY ("ID_Country", "ID_City", "ID_Address", "ID_SubGroup1", "ID_SubGroup3", "ID_SubGroup2")
        REFERENCES public."tCountriesCitiesAddresses" ("ID_Country", "ID_City", "ID_Address", "ID_SubGroup1", "ID_SubGroup3", "ID_SubGroup2")
        ON UPDATE CASCADE
        ON DELETE SET NULL);
CREATE TABLE public."tHumanContacts"
(
    "ID" serial not null,
    "ID_Person" integer not null,
    "Date" timestamp with time zone NOT NULL,
    "Note" text,
  constraint "pk_tHumanContacts" primary key ("ID"),
constraint "fk_tHumanContacts_tPersons" foreign key ("ID_Person") references "tPersons"("ID") on update cascade on delete cascade

);
CREATE TABLE public."tHumanContactsPersons"
(
    "ID_HumanContact" integer not null,
    "ID_Person" integer not null,
  constraint "pk_tHumanContactsPersons" primary key ("ID_HumanContact","ID_Person"),
constraint "fk_tHumanContactsPersons_tHumanContacts" foreign key ("ID_HumanContact") references "tHumanContacts"("ID") on update cascade on delete cascade,
constraint "fk_tHumanContactsPersons_tPersons" foreign key ("ID_Person") references "tPersons"("ID") on update cascade on delete set null);
CREATE TABLE public."tHumanContactsPlaces"
(
    "ID_HumanContact" integer not null,
    "ID_Place" integer not null,
  constraint "pk_tHumanContactsPlaces" primary key ("ID_HumanContact","ID_Place"),
constraint "fk_tHumanContactsPlaces_tHumanContacts" foreign key ("ID_HumanContact") references "tHumanContacts"("ID") on update cascade on delete cascade,
constraint "fk_tHumanContactsPlaces_tPlaces" foreign key ("ID_Place") references "tPlaces"("ID") on update cascade on delete restrict);
alter TABLE public."tSettings"
  add "DeleteHumanContactsAfterDays" integer not null default 90;
alter TABLE  public."tContactsTypes"
  ALTER COLUMN "Name" TYPE character varying(20);
alter TABLE  public."tContactsTypes"
  add "Url" character varying(25);
create TABLE public."tPlacesContacts"
(
    "ID_Place" integer NOT NULL,
    "ID_Contact" integer NOT NULL,
    "ID_ContactType" integer NOT NULL,
    "Contact" character varying(45) COLLATE pg_catalog."default" NOT NULL,
    "Note" text COLLATE pg_catalog."default",
    CONSTRAINT "pk_tPlacesContacts" PRIMARY KEY ("ID_Place", "ID_Contact"),
    CONSTRAINT "fk_tPlacesContacts_tPlace" FOREIGN KEY ("ID_Place")
        REFERENCES public."tPlaces" ("ID")
        ON UPDATE CASCADE
        ON DELETE CASCADE,
    CONSTRAINT "fk_tPlacesContacts_tContactsTypes" FOREIGN KEY ("ID_ContactType")
        REFERENCES public."tContactsTypes" ("ID")
        ON UPDATE CASCADE
        ON DELETE RESTRICT
);
alter table "tPatients" add "Pregnant_Since" date;
alter TABLE "tSettings" add "NeedExport" boolean not null default false;
comment on column "tSettings"."NeedExport" is 'Indication, for the healthorexport project, if there were changes and then if a new export of the data has to be done (this flag is set via triggers on almost all the tables)';
alter TABLE "tSettings" add "DurationBackupCompressed" smallint not null default 0;
comment on column "tSettings"."DurationBackupCompressed" is 'How many seconds took the last backup with the compression';
alter TABLE "tSettings" add "DurationBackup" smallint not null default 0;
comment on column "tSettings"."DurationBackup" is 'How many seconds took the last backup taken without the compression';
alter TABLE "tSettings" add "LastBackup" timestamp with time zone;
CREATE FUNCTION public."ftrSettingsNeedExportSet"()
    RETURNS trigger
    LANGUAGE 'plpgsql'
AS $$
BEGIN
  UPDATE "tSettings"
  set "NeedExport"=true
  where "ID"=1;
  if ( TG_OP = 'DELETE' ) then
    return OLD;
  else
    return NEW;
  end if;
END;
$$;
CREATE TRIGGER "trAllergies_NeedExport" AFTER INSERT OR UPDATE OR DELETE ON "tAllergies" EXECUTE PROCEDURE "ftrSettingsNeedExportSet"();
CREATE TRIGGER "trAllergiesSolutionsDrugs_NeedExport" AFTER INSERT OR UPDATE OR DELETE ON "tAllergiesSolutionsDrugs" EXECUTE PROCEDURE "ftrSettingsNeedExportSet"();
CREATE TRIGGER "trDocuments_NeedExport" AFTER INSERT OR UPDATE OR DELETE ON "tDocuments" EXECUTE PROCEDURE "ftrSettingsNeedExportSet"();
CREATE TRIGGER "trDocumentsFiles_NeedExport" AFTER INSERT OR UPDATE OR DELETE ON "tDocumentsFiles" EXECUTE PROCEDURE "ftrSettingsNeedExportSet"();
CREATE TRIGGER "trDrugs_NeedExport" AFTER INSERT OR UPDATE OR DELETE ON "tDrugs" EXECUTE PROCEDURE "ftrSettingsNeedExportSet"();
CREATE TRIGGER "trDrugsPrescriptions_NeedExport" AFTER INSERT OR UPDATE OR DELETE ON "tDrugsPrescriptions" EXECUTE PROCEDURE "ftrSettingsNeedExportSet"();
CREATE TRIGGER "trExaminations_NeedExport" AFTER INSERT OR UPDATE OR DELETE ON "tExaminations" EXECUTE PROCEDURE "ftrSettingsNeedExportSet"();
CREATE TRIGGER "trExaminationsPeriodical_NeedExport" AFTER INSERT OR UPDATE OR DELETE ON "tExaminationsPeriodical" EXECUTE PROCEDURE "ftrSettingsNeedExportSet"();
CREATE TRIGGER "trExaminationsProblems_NeedExport" AFTER INSERT OR UPDATE OR DELETE ON "tExaminationsProblems" EXECUTE PROCEDURE "ftrSettingsNeedExportSet"();
CREATE TRIGGER "trExemptionsAndMore_NeedExport" AFTER INSERT OR UPDATE OR DELETE ON "tExemptionsAndMore" EXECUTE PROCEDURE "ftrSettingsNeedExportSet"();
CREATE TRIGGER "trHospitalizations_NeedExport" AFTER INSERT OR UPDATE OR DELETE ON "tHospitalizations" EXECUTE PROCEDURE "ftrSettingsNeedExportSet"();
CREATE TRIGGER "trHumanContacts_NeedExport" AFTER INSERT OR UPDATE OR DELETE ON "tHumanContacts" EXECUTE PROCEDURE "ftrSettingsNeedExportSet"();
CREATE TRIGGER "trHumanContactsPersons_NeedExport" AFTER INSERT OR UPDATE OR DELETE ON "tHumanContactsPersons" EXECUTE PROCEDURE "ftrSettingsNeedExportSet"();
CREATE TRIGGER "trHumanContactsPlaces_NeedExport" AFTER INSERT OR UPDATE OR DELETE ON "tHumanContactsPlaces" EXECUTE PROCEDURE "ftrSettingsNeedExportSet"();
CREATE TRIGGER "trLife_NeedExport" AFTER INSERT OR UPDATE OR DELETE ON "tLife" EXECUTE PROCEDURE "ftrSettingsNeedExportSet"();
CREATE TRIGGER "trLifeDetails_NeedExport" AFTER INSERT OR UPDATE OR DELETE ON "tLifeDetails" EXECUTE PROCEDURE "ftrSettingsNeedExportSet"();
CREATE TRIGGER "trMeasurements_NeedExport" AFTER INSERT OR UPDATE OR DELETE ON "tMeasurements" EXECUTE PROCEDURE "ftrSettingsNeedExportSet"();
CREATE TRIGGER "trMeasurementsDetails_NeedExport" AFTER INSERT OR UPDATE OR DELETE ON "tMeasurementsDetails" EXECUTE PROCEDURE "ftrSettingsNeedExportSet"();
CREATE TRIGGER "trPathologies_NeedExport" AFTER INSERT OR UPDATE OR DELETE ON "tPathologies" EXECUTE PROCEDURE "ftrSettingsNeedExportSet"();
CREATE TRIGGER "trPatients_NeedExport" AFTER INSERT OR UPDATE OR DELETE ON "tPatients" EXECUTE PROCEDURE "ftrSettingsNeedExportSet"();
CREATE TRIGGER "trPatientsPathologies_NeedExport" AFTER INSERT OR UPDATE OR DELETE ON "tPatientsPathologies" EXECUTE PROCEDURE "ftrSettingsNeedExportSet"();
CREATE TRIGGER "trPersons_NeedExport" AFTER INSERT OR UPDATE OR DELETE ON "tPersons" EXECUTE PROCEDURE "ftrSettingsNeedExportSet"();
CREATE TRIGGER "trPersonsContacts_NeedExport" AFTER INSERT OR UPDATE OR DELETE ON "tPersonsContacts" EXECUTE PROCEDURE "ftrSettingsNeedExportSet"();
CREATE TRIGGER "trPlaces_NeedExport" AFTER INSERT OR UPDATE OR DELETE ON "tPlaces" EXECUTE PROCEDURE "ftrSettingsNeedExportSet"();
CREATE TRIGGER "trPlacesContacts_NeedExport" AFTER INSERT OR UPDATE OR DELETE ON "tPlacesContacts" EXECUTE PROCEDURE "ftrSettingsNeedExportSet"();
CREATE TRIGGER "trPrescriptions_NeedExport" AFTER INSERT OR UPDATE OR DELETE ON "tPrescriptions" EXECUTE PROCEDURE "ftrSettingsNeedExportSet"();
CREATE TRIGGER "trProblems_NeedExport" AFTER INSERT OR UPDATE OR DELETE ON "tProblems" EXECUTE PROCEDURE "ftrSettingsNeedExportSet"();
alter table "tAgendaDrugs" add "Quantity" real;
alter table "tDocuments" add "SafeLife" boolean not null default false;
alter table "tDocumentsFiles" add "SafeLife" boolean not null default false;
alter table "tDrugsPrescriptions" drop constraint "ck_tDrugsPrescriptions_EveryType";
alter table "tDrugsPrescriptions" add
CONSTRAINT "ck_tDrugsPrescriptions_EveryType" CHECK (("EveryType" = ANY (ARRAY['H'::bpchar, 'D'::bpchar, 'W'::bpchar, 'M'::bpchar, 'N'::bpchar, 'Y'::bpchar])));
COMMENT ON COLUMN "tDrugsPrescriptions"."EveryType" IS 'H = every X hours
D = every X days
W = every X weeks
M = every X months
N = when necessary
Y = every X years';
alter table "tDrugsPrescriptions" add "AlsoWhenNecessary" boolean default false not null;
create table "tDrugsNamesConflicts" (
"ID_DrugName1" integer NOT NULL,
"ID_DrugName2" integer NOT NULL,
"ConflictHours" real not null,
"Note" text,
constraint "pktDrugsNamesConflicts" primary key ("ID_DrugName1","ID_DrugName2"),
CONSTRAINT "fk_tDrugsNamesConflicts_tDrugsNames1" FOREIGN KEY ("ID_DrugName1") REFERENCES "tDrugsNames"("ID") ON UPDATE CASCADE ON DELETE RESTRICT,
CONSTRAINT "fk_tDrugsNamesConflicts_tDrugsNames2" FOREIGN KEY ("ID_DrugName2") REFERENCES "tDrugsNames"("ID") ON UPDATE CASCADE ON DELETE RESTRICT);
comment on table "tDrugsNamesConflicts" is 'Here you can say that, i.e, the A drug can''t be taken together with the B drug because they are in conflict and you have to wait at least X hours between them';
create TABLE "tContactsCategories"
(
    "ID" serial NOT NULL,
	"Name" character varying(20) NOT NULL,
    "System" boolean NOT NULL DEFAULT false,
    CONSTRAINT "pk_tContactsCategories" PRIMARY KEY ("ID")
);
COMMENT ON COLUMN "tContactsCategories"."System"
    IS 'It indicates if this entry was created by the "system" (the software). If yes, the user can''t change/delete it.';
alter TABLE "tHospitalsContacts" add
  "ID_ContactCategory" integer;
alter TABLE "tHospitalsContacts" add
  constraint "fk_tHospitalsContacts_tContactsCategories"
    foreign key ("ID_ContactCategory")
	  references "tContactsCategories"("ID")
	    on update cascade
		on delete set null;
alter TABLE "tHospitalsWardsContacts" add
  "ID_ContactCategory" integer;
alter TABLE "tHospitalsWardsContacts" add
  constraint "fk_tHospitalsWardsContacts_tContactsCategories"
    foreign key ("ID_ContactCategory")
	  references "tContactsCategories"("ID")
	    on update cascade
		on delete set null;
alter TABLE "tPersonsContacts" add
  "ID_ContactCategory" integer;
alter TABLE "tPersonsContacts" add
  constraint "fk_tPersonsContacts_tContactsCategories"
    foreign key ("ID_ContactCategory")
	  references "tContactsCategories"("ID")
	    on update cascade
		on delete set null;
CREATE TABLE public."tContactsCategoriesPerson"
(
    "ID" serial NOT NULL,
    "Name" character varying(20) NOT NULL,
    "System" boolean NOT NULL DEFAULT false,
    CONSTRAINT "pk_tContactsCategoriesPerson" PRIMARY KEY ("ID")
);
COMMENT ON COLUMN public."tContactsCategoriesPerson"."System"
    IS 'It indicates if this entry was created by the "system" (the software). If yes, the user can''t change/delete it.';
CREATE TABLE public."tPatientsContactsCategoriesPerson"
(
    "ID_Patient" integer NOT NULL,
    "Order" integer NOT NULL,
    "ID_ContactCategoryPerson" integer NOT NULL,
    "COD_Person" integer NOT NULL,
    "Note" text,
    CONSTRAINT "pk_tPatientsContactsCategoriesPerson" PRIMARY KEY ("ID_Patient", "COD_Person"),
    CONSTRAINT "fk_tPatientsContactsCategoriesPerson_tCCP" FOREIGN KEY ("ID_ContactCategoryPerson")
        REFERENCES public."tContactsCategoriesPerson" ("ID")
        ON UPDATE CASCADE
        ON DELETE RESTRICT,
    CONSTRAINT "fk_tPatientsContactsCategoriesPerson_tPerson" FOREIGN KEY ("COD_Person")
        REFERENCES public."tPersons" ("ID")
        ON UPDATE CASCADE
        ON DELETE CASCADE
);
CREATE TRIGGER "trPatientsContactsCategoriesPerson_NeedExport"
    AFTER INSERT OR DELETE OR UPDATE 
    ON public."tPatientsContactsCategoriesPerson"
    EXECUTE PROCEDURE public."ftrSettingsNeedExportSet"();
alter TABLE "tPatients" add "NeedExport" boolean not null default false;
-- Rename of examinations -
CREATE TABLE public."tExaminationsNamesRenamed"
(
	"ID" serial not null,
    "Name" character varying(384) NOT NULL,
    "Origin" character varying(15),
    "Expired" boolean NOT NULL DEFAULT false,
    "ID_ExaminationNameCategory" integer,
    CONSTRAINT "pk_tExaminationsNamesRenamed" PRIMARY KEY ("ID"),
    CONSTRAINT "udx_tExaminationsNamesRenamed_Name" UNIQUE ("Name"),
    CONSTRAINT "fk_tExaminationsNamesRenamed_tExaminationsNamesCategories" FOREIGN KEY ("ID_ExaminationNameCategory")
        REFERENCES public."tExaminationsNamesCategories" ("ID")
        ON UPDATE CASCADE
        ON DELETE RESTRICT
);
COMMENT ON COLUMN public."tExaminationsNamesRenamed"."Origin"
    IS 'It will be used to know if this entry comes from an automation import and, if yes (field not empty), from which one.';
CREATE TABLE public."tExaminationsNamesRenamedNames"
(
	"ID_ExaminationsNamesRenamed" INTEGER not null,
    "ID_ExaminationsNames" integer not null,
    CONSTRAINT "pk_tExaminationsNamesRenamedNames" PRIMARY KEY ("ID_ExaminationsNamesRenamed","ID_ExaminationsNames"),
    CONSTRAINT "fk_tExaminationsNamesRenamedNames_tExaminationsNamesRenamed" FOREIGN KEY ("ID_ExaminationsNamesRenamed")
        REFERENCES public."tExaminationsNamesRenamed" ("ID")
        ON UPDATE CASCADE
        ON DELETE CASCADE,
    CONSTRAINT "fk_tExaminationsNamesRenamedNames_tExaminationsNames" FOREIGN KEY ("ID_ExaminationsNames")
        REFERENCES public."tExaminationsNames" ("ID")
        ON UPDATE CASCADE
        ON DELETE CASCADE
);
-- ----------
update "tSettings"
set "DbVersion"=6
where "ID"=1;
